# -*- coding: utf-8 -*-
import frappe
from frappe.model.document import Document
from frappe.utils import flt, cint, nowdate, nowtime, get_datetime, format_datetime
from frappe.permissions import add_permission

class ScrapIssue(Document):
    """
    余料出库单控制器
    处理余料出库单的数据验证和业务逻辑
    """
    
    def validate(self):
        """验证数据有效性"""
        self.validate_issue_id()
        self.validate_warehouse()
        self.validate_scrap_materials()
        self.set_issue_date()
    
    def validate_issue_id(self):
        """验证出库单编号唯一性"""
        if not self.issue_id:
            self.issue_id = self.generate_issue_id()
            return
        
        # 检查编号唯一性
        if frappe.db.exists("Scrap Issue", {"issue_id": self.issue_id, "name": ["!=", self.name]}):
            frappe.throw(f"出库单编号 {self.issue_id} 已存在，请使用其他编号")
    
    def generate_issue_id(self):
        """生成出库单编号"""
        # 格式: SI-YYYYMMDD-NNNN
        from frappe.model.naming import make_autoname
        return make_autoname("SI-.YYYYMMDD-.#####")
    
    def validate_warehouse(self):
        """验证仓库有效性"""
        if not self.warehouse:
            frappe.throw("请选择出库仓库")
        
        # 检查仓库是否存在
        if not frappe.db.exists("Scrap Warehouse", self.warehouse):
            frappe.throw(f"仓库 {self.warehouse} 不存在")
        
        # 检查仓库状态
        warehouse_status = frappe.db.get_value("Scrap Warehouse", self.warehouse, "status")
        if warehouse_status != "启用":
            frappe.throw(f"仓库 {self.warehouse} 状态为 {warehouse_status}，无法使用")
    
    def validate_scrap_materials(self):
        """验证余料列表"""
        if not self.scrap_materials or len(self.scrap_materials) == 0:
            frappe.throw("请添加至少一项余料")
        
        # 验证每个余料项
        for item in self.scrap_materials:
            if not item.scrap_material:
                frappe.throw("请选择余料")
            
            if not item.location:
                frappe.throw("请选择库位")
            
            if not item.quantity or flt(item.quantity) <= 0:
                frappe.throw("出库数量必须大于0")
            
            # 检查余料状态
            scrap_material_status = frappe.db.get_value("Scrap Material", item.scrap_material, "status")
            if scrap_material_status != "可用":
                frappe.throw(f"余料 {item.scrap_material} 状态为 {scrap_material_status}，无法出库")
            
            # 检查余料是否在指定库位
            scrap_material_location = frappe.db.get_value("Scrap Material", item.scrap_material, "location")
            if scrap_material_location != item.location:
                frappe.throw(f"余料 {item.scrap_material} 不在库位 {item.location} 中")
            
            # 检查出库数量是否超过可用数量
            available_quantity = frappe.db.get_value("Scrap Material", item.scrap_material, "quantity")
            if flt(item.quantity) > flt(available_quantity):
                frappe.throw(f"余料 {item.scrap_material} 出库数量 {item.quantity} 超过可用数量 {available_quantity}")
    
    def set_issue_date(self):
        """设置出库日期"""
        if not self.issue_date:
            self.issue_date = nowdate()
    
    def before_submit(self):
        """提交前处理"""
        # 检查状态
        if self.status != "已审核":
            frappe.throw("只有已审核的出库单才能提交")
        
        # 设置提交信息
        self.submitted_by = frappe.session.user
        self.submitted_date = get_datetime()
        
        # 更新余料状态和数量
        self.update_scrap_materials()
        
        # 创建出库事务记录
        self.create_issue_transaction()
    
    def on_submit(self):
        """提交后处理"""
        # 更新余料状态为已出库
        for item in self.scrap_materials:
            # 如果余料数量全部出库，则状态设为已出库
            available_quantity = frappe.db.get_value("Scrap Material", item.scrap_material, "quantity")
            if flt(item.quantity) >= flt(available_quantity):
                frappe.db.set_value("Scrap Material", item.scrap_material, "status", "已出库")
            else:
                # 如果部分出库，则状态仍为可用，但数量减少
                new_quantity = flt(available_quantity) - flt(item.quantity)
                frappe.db.set_value("Scrap Material", item.scrap_material, "quantity", new_quantity)
    
    def before_cancel(self):
        """取消前处理"""
        # 检查是否可以取消
        if self.status not in ["已审核", "草稿"]:
            frappe.throw(f"状态为 {self.status} 的出库单无法取消")
    
    def on_cancel(self):
        """取消后处理"""
        # 恢复余料状态和数量
        for item in self.scrap_materials:
            # 恢复余料数量
            current_quantity = frappe.db.get_value("Scrap Material", item.scrap_material, "quantity")
            new_quantity = flt(current_quantity) + flt(item.quantity)
            frappe.db.set_value("Scrap Material", item.scrap_material, "quantity", new_quantity)
            
            # 如果余料之前状态为已出库，则恢复为可用
            current_status = frappe.db.get_value("Scrap Material", item.scrap_material, "status")
            if current_status == "已出库":
                frappe.db.set_value("Scrap Material", item.scrap_material, "status", "可用")
        
        # 创建取消事务记录
        self.create_cancel_transaction()
    
    def update_scrap_materials(self):
        """更新余料状态和数量"""
        for item in self.scrap_materials:
            # 减少余料数量
            current_quantity = frappe.db.get_value("Scrap Material", item.scrap_material, "quantity")
            new_quantity = flt(current_quantity) - flt(item.quantity)
            frappe.db.set_value("Scrap Material", item.scrap_material, "quantity", new_quantity)
    
    def create_issue_transaction(self):
        """创建出库事务记录"""
        for item in self.scrap_materials:
            doc = frappe.new_doc("Scrap Transaction")
            doc.transaction_type = "出库"
            doc.transaction_date = self.issue_date
            doc.scrap_material = item.scrap_material
            doc.warehouse = self.warehouse
            doc.location = item.location
            doc.quantity = item.quantity
            doc.reference_doctype = "Scrap Issue"
            doc.reference_name = self.name
            doc.notes = f"出库单 {self.issue_id} 出库"
            doc.insert(ignore_permissions=True)
    
    def create_cancel_transaction(self):
        """创建取消事务记录"""
        for item in self.scrap_materials:
            doc = frappe.new_doc("Scrap Transaction")
            doc.transaction_type = "入库"
            doc.transaction_date = nowdate()
            doc.scrap_material = item.scrap_material
            doc.warehouse = self.warehouse
            doc.location = item.location
            doc.quantity = item.quantity
            doc.reference_doctype = "Scrap Issue"
            doc.reference_name = self.name
            doc.notes = f"取消出库单 {self.issue_id}"
            doc.insert(ignore_permissions=True)
    
    def calculate_total_quantity(self):
        """计算总数量"""
        total_quantity = 0
        for item in self.scrap_materials:
            total_quantity += flt(item.quantity)
        self.total_quantity = total_quantity
    
    def submit_for_approval(self):
        """提交审批"""
        if self.status != "草稿":
            frappe.throw("只有草稿状态的出库单才能提交审批")
        
        self.status = "待审核"
        self.submitted_by = frappe.session.user
        self.submitted_date = get_datetime()
        self.save()
        
        # 发送通知给审核人
        self.send_approval_notification()
    
    def approve(self, approve=True):
        """审批处理"""
        if self.status != "待审核":
            frappe.throw("只有待审核状态的出库单才能进行审批")
        
        if approve:
            self.status = "已审核"
            self.approved_by = frappe.session.user
            self.approved_date = get_datetime()
        else:
            self.status = "已拒绝"
            self.approved_by = frappe.session.user
            self.approved_date = get_datetime()
        
        self.save()
        
        # 发送审批结果通知
        self.send_approval_result_notification(approve)
    
    def send_approval_notification(self):
        """发送审批通知"""
        # 获取审核人列表
        approvers = frappe.db.get_all("Has Role", {
            "role": "Scrap Manager"
        }, pluck="parent")
        
        if not approvers:
            return
        
        # 发送通知
        for approver in approvers:
            frappe.sendmail(
                recipients=[approver],
                subject=f"余料出库单审批通知 - {self.issue_id}",
                message=f"""
                <p>您好，</p>
                <p>有一张余料出库单需要您的审批：</p>
                <ul>
                    <li>出库单编号：{self.issue_id}</li>
                    <li>出库日期：{self.issue_date}</li>
                    <li>出库仓库：{self.warehouse}</li>
                    <li>出库类型：{self.issue_type}</li>
                    <li>提交人：{self.submitted_by}</li>
                    <li>提交时间：{format_datetime(self.submitted_date)}</li>
                </ul>
                <p>请登录系统进行审批。</p>
                <p>谢谢！</p>
                """,
                reference_doctype=self.doctype,
                reference_name=self.name
            )
    
    def send_approval_result_notification(self, approved):
        """发送审批结果通知"""
        if not self.submitted_by:
            return
        
        # 发送通知给提交人
        frappe.sendmail(
            recipients=[self.submitted_by],
            subject=f"余料出库单审批结果 - {self.issue_id}",
            message=f"""
            <p>您好，</p>
            <p>您提交的余料出库单已经审批完成：</p>
            <ul>
                <li>出库单编号：{self.issue_id}</li>
                <li>审批结果：{"已通过" if approved else "已拒绝"}</li>
                <li>审批人：{self.approved_by}</li>
                <li>审批时间：{format_datetime(self.approved_date)}</li>
            </ul>
            <p>请登录系统查看详情。</p>
            <p>谢谢！</p>
            """,
            reference_doctype=self.doctype,
            reference_name=self.name
        )
    
    @frappe.whitelist()
    def get_issue_list(self, status=None, warehouse=None, from_date=None, to_date=None):
        """获取出库单列表"""
        filters = {}
        
        if status:
            filters["status"] = status
        if warehouse:
            filters["warehouse"] = warehouse
        if from_date:
            filters["issue_date"] = [">=", from_date]
        if to_date:
            filters["issue_date"] = ["<=", to_date]
        
        return frappe.db.get_all("Scrap Issue",
            filters=filters,
            fields=["name", "issue_id", "issue_date", "warehouse", "issue_type", "status", "total_quantity"],
            order_by="issue_date desc"
        )
    
    @frappe.whitelist()
    def get_pending_approvals(self):
        """获取待审批的出库单"""
        return frappe.db.get_all("Scrap Issue",
            filters={"status": "待审核"},
            fields=["name", "issue_id", "issue_date", "warehouse", "issue_type", "submitted_by", "submitted_date"],
            order_by="submitted_date desc"
        )